﻿namespace Patterns4Net.Tests.Core.Conventions
{
    using System.Diagnostics.Contracts;
    using System.Linq;
    using Mono.Cecil;
    using NUnit.Framework;
    using Patterns4Net.Core;
    using Patterns4Net.Core.CecilExtensions;
    using Patterns4Net.Core.Patterns;

    [TestFixture]
    public class ClassNameConventionTest
    {
        [Test]
        [Category("Integration")]
        public void Convention_Created_With_FactoryMethod_StartsWith_Matches_This_Class()
        {
            var convention = NameConvention.StartsWith("Class", t => new Immutable((TypeDefinition)t, false));
            this.TestConventionReturnsImmutable(convention);
        }

        [Test]
        [Category("Integration")]
        public void Convention_Created_With_FactoryMethod_StartsWith_Does_Not_Match_This_Class()
        {
            var convention = NameConvention.StartsWith("ABC", t => new Immutable((TypeDefinition)t, false));
            this.TestConventionReturnsNothing(convention);
        }

        [Test]
        [Category("Integration")]
        public void Convention_Created_With_FactoryMethod_EndsWith_Matches_This_Class()
        {
            var convention = NameConvention.EndsWith("Test", t => new Immutable((TypeDefinition)t, false));
            this.TestConventionReturnsImmutable(convention);
        }

        [Test]
        [Category("Integration")]
        public void Convention_Created_With_FactoryMethod_Contains_Matches_This_Class()
        {
            var convention = NameConvention.Contains("Convention", t => new Immutable((TypeDefinition)t, false));
            this.TestConventionReturnsImmutable(convention);
        }

        private void TestConventionReturnsImmutable(NameConvention convention)
        {
            Contract.Requires(convention != null);
            Contract.Assume(this.GetType() != null);
            var result = convention.GetPatterns(this.GetType().GetTypeDefinition());
            CollectionAssert.AreEquivalent(
                new[] { typeof(Immutable) },
                result.Select(x => x.GetType()));
        }

        private void TestConventionReturnsNothing(NameConvention convention)
        {
            Contract.Requires(convention != null);
            Contract.Assume(this.GetType() != null);
            var result = convention.GetPatterns(this.GetType().GetTypeDefinition());
            CollectionAssert.IsEmpty(result);
        }
    }
}
